/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.springblade.modules.repair.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.AllArgsConstructor;
import org.springblade.common.config.ProjectApiConfiguration;
import org.springblade.common.utils.AsyncHttpUtil;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.DateTimeUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.WebUtil;
import org.springblade.modules.repair.dto.UserSignDetailDTO;
import org.springblade.modules.repair.dto.sign.SignDetailSearchDTO;
import org.springblade.modules.repair.entity.MaintainSignSeting;
import org.springblade.modules.repair.entity.UserSignDetail;
import org.springblade.modules.repair.entity.UserSignDetailHistory;
import org.springblade.modules.repair.service.IBuildingService;
import org.springblade.modules.repair.service.IMaintainSignSetingService;
import org.springblade.modules.repair.service.IUserSignDetailHistoryService;
import org.springblade.modules.repair.service.IUserSignDetailService;
import org.springblade.modules.repair.utils.DistanceUtils;
import org.springblade.modules.repair.vo.DateResultVo;
import org.springblade.modules.repair.vo.UserSignDetailHomeVo;
import org.springblade.modules.repair.vo.UserSignDetailResultVo;
import org.springblade.modules.repair.vo.plan.SignRangeVo;
import org.springblade.modules.repair.vo.sign.*;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;

/**
 * 用户签到明细表 控制器
 *
 * @author zcc
 * @since 2021-07-28
 */
@RestController
@AllArgsConstructor
@RequestMapping("repair/user/sign")
@Api(value = "用户签到明细", tags = "用户签到明细表接口")
public class UserSignDetailController extends BladeController {

	private final IUserSignDetailService userSignDetailService;

	private final IMaintainSignSetingService maintainSignSetingService;

	private final IUserSignDetailHistoryService userSignDetailHistoryService;

	private final IBuildingService buildingService;

	private final AsyncHttpUtil asyncHttpUtil;

	private final ProjectApiConfiguration projectApiConfiguration;


	@GetMapping("/home/info")
	@ApiOperation("获取签到首页数据")
	public R<UserSignDetailHomeVo> getHomeData(Integer month, String searchYear) {
		if (month == null) {
			month = Convert.toInt(DateUtil.format(new Date(), "MM"));
		}
		String year = DateUtil.format(DateUtil.beginOfMonth(new Date()), "yyyy");
		if (StrUtil.isNotEmpty(searchYear)) {
			year = searchYear;
		}
		if (month.equals(1)) {
			year = year + "-01-01";
		} else if (month == 2) {
			year = year + "-02-01";
		} else if (month == 3) {
			year = year + "-03-01";
		} else if (month == 4) {
			year = year + "-04-01";
		} else if (month == 5) {
			year = year + "-05-01";
		} else if (month == 6) {
			year = year + "-06-01";
		} else if (month == 7) {
			year = year + "-07-01";
		} else if (month == 8) {
			year = year + "-08-01";
		} else if (month == 9) {
			year = year + "-09-01";
		} else if (month == 10) {
			year = year + "-10-01";
		} else if (month == 11) {
			year = year + "-11-01";
		} else if (month == 12) {
			year = year + "-12-01";
		}

		Integer beginDate = Convert.toInt(DateUtil.format(DateUtil.beginOfMonth(DateUtil.parse(year)), "yyyyMMdd"));
		Integer endDate = Convert.toInt(DateUtil.format(DateUtil.endOfMonth(DateUtil.parse(year)), "yyyyMMdd"));
		Long userId = AuthUtil.getUserId();
		List<UserSignDetail> list = userSignDetailService.list(userId, beginDate, endDate);
		UserSignDetailHomeVo userSignDetailHomeVo = new UserSignDetailHomeVo();
		userSignDetailHomeVo.setList(list);
		MaintainSignSeting maintainSignSeting = maintainSignSetingService.getMaintainSignSetingByUserId(userId);
		if (maintainSignSeting == null) {
			return R.fail("你暂未参与任何考勤组，无法操作");
		}
		userSignDetailHomeVo.setSignSettingName(getSignSettingName(maintainSignSeting));
		return R.data(userSignDetailHomeVo);
	}

	@GetMapping("/detail")
	@ApiOperation("根据日期获取考勤详情")
	public R<UserSignDetailResultVo> getSignSettingDetail(Integer date) {

		UserSignDetail userSignDetail = userSignDetailService.getOne(Wrappers.<UserSignDetail>lambdaQuery().eq(UserSignDetail::getUserId, AuthUtil.getUserId()).eq(UserSignDetail::getSignDate, date));

		UserSignDetailResultVo userSignDetailResultVo = new UserSignDetailResultVo();
		if (userSignDetail == null) {
			return R.fail("你暂未参与任何考勤组,无法操作");
		}
		MaintainSignSeting maintainSignSeting = maintainSignSetingService.getById(userSignDetail.getSignSettingId());
		if (maintainSignSeting == null) {
			return R.fail("你暂未参与任何考勤组，无法操作");
		}
		final String hHmm = userSignDetail.getSignDate() + DateUtil.format(DateUtil.parseTimeToday(maintainSignSeting.getSignDate()), "HHmm");
		final String hHmm2 = userSignDetail.getSignDate() + DateUtil.format(DateUtil.parseTimeToday(maintainSignSeting.getSignOutDate()), "HHmm");

		userSignDetailResultVo.setUserSignTime(DateUtil.parse(hHmm, "yyyyMMddHHmm").getTime());
		userSignDetailResultVo.setUserSignOutTime(DateUtil.parse(hHmm2, "yyyyMMddHHmm").getTime());

		userSignDetailResultVo.setId(userSignDetail.getId());
		userSignDetailResultVo.setSignAddress(userSignDetail.getSignAddress());
		userSignDetailResultVo.setSignOutAddress(userSignDetail.getSignOutAddress());
		userSignDetailResultVo.setSignBeLate(userSignDetail.getSignBeLate());
		userSignDetailResultVo.setSignOutLeaveEarly(userSignDetail.getSignOutLeaveEarly());
		if (userSignDetail.getSignTime() != null) {
			userSignDetailResultVo.setUserSignDate(DateUtil.format(new Date(userSignDetail.getSignTime()), "yyyy-MM-dd HH:mm"));
		}
		if (userSignDetail.getSignOutTime() != null) {
			userSignDetailResultVo.setUserSignOutDate(DateUtil.format(new Date(userSignDetail.getSignOutTime()), "yyyy-MM-dd HH:mm"));
		}

		userSignDetailResultVo.setSignType(userSignDetail.getSignType());
		userSignDetailResultVo.setSignOutType(userSignDetail.getSignOutType());
		userSignDetailResultVo.setNewSign(userSignDetail.getNewSign());
		userSignDetailResultVo.setNewSignTime(userSignDetail.getNewSignTime());
		userSignDetailResultVo.setNewSignOut(userSignDetail.getNewSignOut());
		userSignDetailResultVo.setNewSignOutTime(userSignDetail.getNewSignOutTime());
		userSignDetailResultVo.setSignRange(maintainSignSeting.getSignRange() == null ? 300 : maintainSignSeting.getSignRange());
		if (date.equals(Convert.toInt(DateUtil.format(new Date(), "yyyyMMdd")))) {
			List<SignRangeVo> signRangeVoList = buildingService.getBuildingSignList();
			userSignDetailResultVo.setSignRangeList(signRangeVoList);
		}

		return R.data(userSignDetailResultVo);

	}

	@PostMapping("/update")
	@ApiOperation("考勤更新")
	public R<Boolean> update(@RequestBody UserSignDetail userSignDetail) {

		/*
		 * 0:迟到 1：正常 ，2 缺勤,3:考勤范围外打卡
		 * */
		Integer signStatus[] = {0, 1, 2, 3};

		/*
		 *1:范围内，2范围外
		 * */
		Integer signType[] = {1, 2};
		if (userSignDetail.getId() == null) {
			return R.fail("考勤ID不能为空");
		}
		UserSignDetail signDetail = userSignDetailService.getById(userSignDetail.getId());
		MaintainSignSeting maintainSignSeting = maintainSignSetingService.getById(signDetail.getSignSettingId());
		if (maintainSignSeting == null) {
			return R.fail("你暂未参与任何考勤组，无法操作");
		}
		DateTime dateTime = DateUtil.parseTimeToday(maintainSignSeting.getSignDate());
		DateTime dateTime1 = DateUtil.parseTimeToday(maintainSignSeting.getSignOutDate());

		List<SignRangeVo> signRangeVoList = buildingService.getBuildingSignList();

		if (signDetail.getSignTime() == null) {

			Long sign = dateTime.getTime();
			signDetail.setSignTime((new Date()).getTime());
			final Integer minute = Convert.toInt(DateUtil.between(new Date(sign), new Date(signDetail.getSignTime()), DateUnit.MINUTE));

			if (sign > signDetail.getSignTime()) {
				signDetail.setSignBeLate(signStatus[1]);
			} else {
				if (minute > 0) {
					signDetail.setSignBeLate(signStatus[0]);
				} else {
					signDetail.setSignBeLate(signStatus[1]);
				}

			}
			signDetail.setSignAddress(userSignDetail.getSignAddress());
			signDetail.setSignLatitude(userSignDetail.getSignLatitude());
			signDetail.setSignLongitude(userSignDetail.getSignLongitude());
			if (userSignDetail.getSignLongitude() == null || userSignDetail.getSignLatitude() == null) {
				return R.fail("请开启签到定位权限");
			}
			for (int i = 0; i < signRangeVoList.size(); i++) {
				signDetail.setSignType(signType[1]);
				SignRangeVo signRangeVo = signRangeVoList.get(i);
				if (StrUtil.isNotEmpty(signRangeVo.getLatitude()) && StrUtil.isNotEmpty(signRangeVo.getLongitude())) {
					BigDecimal distance = DistanceUtils.getDistance(Convert.toDouble(signRangeVo.getLongitude()), Convert.toDouble(signRangeVo.getLatitude()), Convert.toDouble(signDetail.getSignLongitude()), Convert.toDouble(signDetail.getSignLatitude()));
					Integer range = Convert.toInt(distance.toString());
					if (range < maintainSignSeting.getSignRange()) {
						signDetail.setSignType(signType[0]);
						break;
					}
				}
			}

		} else {
			Long signOut = dateTime1.getTime();
			signDetail.setSignOutTime((new Date()).getTime());

			if (signOut <= signDetail.getSignOutTime()) {
				signDetail.setSignOutLeaveEarly(signStatus[1]);
			} else {
				signDetail.setSignOutLeaveEarly(signStatus[0]);
			}
			signDetail.setSignOutAddress(userSignDetail.getSignOutAddress());
			signDetail.setSignOutLatitude(userSignDetail.getSignOutLatitude());
			signDetail.setSignOutLongitude(userSignDetail.getSignOutLongitude());
			if (userSignDetail.getSignOutLatitude() == null || userSignDetail.getSignOutLongitude() == null) {
				return R.fail("请开启签退定位权限");
			}

			for (int i = 0; i < signRangeVoList.size(); i++) {
				signDetail.setSignOutType(signType[1]);
				SignRangeVo signRangeVo = signRangeVoList.get(i);
				if (StrUtil.isNotEmpty(signRangeVo.getLatitude()) && StrUtil.isNotEmpty(signRangeVo.getLongitude())) {
					BigDecimal distance = DistanceUtils.getDistance(Convert.toDouble(signRangeVo.getLongitude()), Convert.toDouble(signRangeVo.getLatitude()), Convert.toDouble(signDetail.getSignOutLongitude()), Convert.toDouble(signDetail.getSignOutLatitude()));
					Integer range = Convert.toInt(distance.toString());
					if (range < maintainSignSeting.getSignRange()) {
						signDetail.setSignOutType(signType[0]);
						break;
					}
				}
			}
		}

		UserSignDetailHistory userSignDetailHistory = new UserSignDetailHistory();
		BeanUtil.copyProperties(signDetail, userSignDetailHistory);
		userSignDetailHistory.setId(null);
		userSignDetailHistory.setSignDetailId(userSignDetail.getId());
		userSignDetailHistoryService.save(userSignDetailHistory);
		String tenantId = AuthUtil.getTenantId();
		UserSignDetailDTO userSignDetailDTO = new UserSignDetailDTO();
		userSignDetailDTO.setUserId(signDetail.getUserId());
		if ("592800".equals(tenantId)) {
			asyncHttpUtil.createPost(projectApiConfiguration.getWeb() + "/admin/lark/galaxy/elevator/daily/attendance/person", Func.toJson(userSignDetailDTO), WebUtil.getRequest());
		}
		return R.data(userSignDetailService.updateById(signDetail));
	}

	private String getSignSettingName(MaintainSignSeting maintainSignSeting) {
		DateTime dateTime = DateUtil.parseTimeToday(maintainSignSeting.getSignDate());
		DateTime dateTime1 = DateUtil.parseTimeToday(maintainSignSeting.getSignOutDate());
		return DateUtil.format(dateTime, "HH:mm") + "上班 - " + DateUtil.format(dateTime1, "HH:mm") + " 下班";

	}

	@GetMapping("/bjOfTime")
	@ApiOperation("获取北京当前时间")
	public R<DateResultVo> getBeiJingTime() {
		LocalDateTime now = LocalDateTime.now(ZoneId.of("UTC+8"));
		DateResultVo dateResultVo = new DateResultVo();
		long time = Date.from(now.atZone(ZoneId.systemDefault()).toInstant()).getTime();
		dateResultVo.setTime(time);
		dateResultVo.setDate(DateUtil.format(new Date(time), "yyyyMMdd"));
		return R.data(dateResultVo);

	}


	@PostMapping("/updateNewSign")
	@ApiOperation("签卡")
	public R<Boolean> updateNewSign(@RequestBody UserSignDetail userSignDetail) {
		UserSignDetail signDetail = userSignDetailService.getById(userSignDetail.getId());
		UserSignDetailHistory userSignDetailHistory = new UserSignDetailHistory();
		//表示补卡
		Integer newSignStatus = 1;

		if (userSignDetail.getSignTime() != null) {
			signDetail.setNewSign(newSignStatus);
			signDetail.setNewSignTime(new Date());
			signDetail.setNewSignDesc(userSignDetail.getSignDesc());
			//表示签到补卡
			Integer status = 2;
			userSignDetailHistory.setStatus(status);
		}
		if (userSignDetail.getSignOutTime() != null) {
			signDetail.setNewSignOut(newSignStatus);
			signDetail.setNewSignOutTime(new Date());
			signDetail.setNewSignOutDesc(userSignDetail.getSignDesc());
			//表示签退补卡
			Integer status = 3;
			userSignDetailHistory.setStatus(status);
		}
		signDetail.setSignDesc(userSignDetail.getSignDesc());
		userSignDetailService.updateById(signDetail);


		BeanUtil.copyProperties(signDetail, userSignDetailHistory);
		userSignDetailHistory.setSignTime(userSignDetail.getSignTime());
		userSignDetailHistory.setSignOutTime(userSignDetail.getSignOutTime());
		userSignDetailHistory.setSignDetailId(signDetail.getId());

		userSignDetailHistory.setId(null);
		return R.data(userSignDetailHistoryService.save(userSignDetailHistory));
	}

	/**
	 * 將yyyyMMddHHmmss格式转为时间戳
	 *
	 * @param date 时间格式yyyyMMddHHmmss格式转为时间戳
	 * @return 时间搓
	 */
	private Long getDate(String date) {
		LocalDateTime yyyyMMddHHmmss = DateTimeUtil.parseDateTime(date, "yyyyMMddHHmmss");
		return Date.from(yyyyMMddHHmmss.atZone(ZoneId.systemDefault()).toInstant()).getTime();
	}


//=====================================================v0.22统计开发=============================================================


	/**
	 * 获取维保员的考勤统计信息
	 *
	 * @param signDetailSearchDTO 查询条件
	 * @return 数据集
	 */
	@PostMapping("getUserSignDetail")
	@ApiOperation("维保员签到统计")
	public R<UserSignDetailVo> getUserSignDetail(@RequestBody SignDetailSearchDTO signDetailSearchDTO) {
		UserSignDetailVo userSignDetailVo = userSignDetailService.getUserSignDetail(signDetailSearchDTO);
		return R.data(userSignDetailVo);
	}


	/**
	 * 获取维保员的考勤统计信息
	 *
	 * @param signDetailSearchDTO 查询条件
	 * @return 数据集
	 */
	@PostMapping("getRestUserSignDetail")
	@ApiOperation("维保组长统计休息日")
	public R<RestUserSignDetailVo> getRestUserSignDetail(@RequestBody SignDetailSearchDTO signDetailSearchDTO) {

		return R.data(userSignDetailService.getRestUserSignDetail(signDetailSearchDTO));
	}

	/**
	 * 获取维保员的考勤统计信息
	 *
	 * @param signDetailSearchDTO 查询条件
	 * @return 数据集
	 */
	@PostMapping("getWorkUserSignDetail")
	@ApiOperation("维保组长统计工作日")
	public R<WorkUserSignDetailVo> getWorkUserSignDetail(@RequestBody SignDetailSearchDTO signDetailSearchDTO) {

		return R.data(userSignDetailService.getWorkUserSignDetail(signDetailSearchDTO));
	}


	/**
	 * 获取维保员的考勤统计信息
	 *
	 * @param signDetailSearchDTO 查询条件
	 * @return 数据集
	 */
	@PostMapping("getDateUserSignDetail")
	@ApiOperation("维保组长周月筛选")
	public R<DateUserSignDetailVo> getDateUserSignDetail(@RequestBody SignDetailSearchDTO signDetailSearchDTO) {

		return R.data(userSignDetailService.getDateUserSignDetail(signDetailSearchDTO));
	}

	/**
	 * 获取考勤所有在职工作人员
	 *
	 * @param userIds 用户ids
	 * @return 数据集
	 */
	@PostMapping("getWorkUserList")
	@ApiOperation("取考勤所有在职工作人员")
	public R<List<SignWorkUserVo>> getWorkUserList(@RequestBody List<Long> userIds) {

		return R.data(userSignDetailService.getWorkUserList(userIds));
	}


	@GetMapping("/getHolidays")
	@ApiOperationSupport(order = 4)
	@ApiOperation(value = "获取年度所有节假日")
	public R getHolidays(@ApiParam(value = "获取年度所有节假日，默认本年") @RequestParam(required = false) Integer year) {
		return R.data(userSignDetailService.getHolidays(year));
	}
}
